package com.realife.eson.common.util.information;


import com.esotericsoftware.yamlbeans.YamlException;
import com.esotericsoftware.yamlbeans.YamlReader;
import com.esotericsoftware.yamlbeans.YamlWriter;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import com.realife.eson.common.asserts.AssertNP;
import com.realife.eson.common.util.common.ResourcesCloseUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.web.multipart.MultipartFile;
import org.yaml.snakeyaml.Yaml;

import java.io.*;
import java.lang.management.ManagementFactory;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import java.util.Properties;

/**
 * @version V1.0
 * @author: guangcheng
 * @date: 2022/5/24 12:42
 * @description:
 */
@SuppressWarnings("all")
@Slf4j
public class MeYamlUtil {

    private MeYamlUtil() {
    }


    /**
     * ================================Jackson=========================================
     */


    /**
     * yamlString 2 obj
     *
     * @param yamlStr 字符串
     * @param clazz   目标类
     * @param <T>     泛型
     * @return 目标类
     */
    public static <T> T toObjectJack(String yamlStr, Class<T> clazz) {
        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
        mapper.findAndRegisterModules();
        try {
            return mapper.readValue(yamlStr, clazz);
        } catch (Exception e) {
            log.info("[**======> {} **]", e.getMessage() + " >> " + e.getStackTrace()[0] + " >> " + e.getCause());
        }
        return null;
    }

    /**
     * obj 2 yamlString
     *
     * @param object 对象
     * @return yaml字符串
     */
    public static String toYamlJack(Object object) {
        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
        mapper.findAndRegisterModules();
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        mapper = new ObjectMapper(new YAMLFactory().disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER));
        StringWriter stringWriter = new StringWriter();
        try {
            mapper.writeValue(stringWriter, object);
            return stringWriter.toString();
        } catch (Exception e) {
            log.info("[**======> {} **]", e.getMessage() + " >> " + e.getStackTrace()[0] + " >> " + e.getCause());
        }
        return "";
    }

    /**
     * json 2 yaml
     *
     * @param jsonStr json
     * @return yaml
     * @throws JsonProcessingException Exception
     */
    public static String json2YamlJack(String jsonStr) {
        try {
            JsonNode jsonNode = new ObjectMapper().readTree(jsonStr);
            return new YAMLMapper().writeValueAsString(jsonNode);
        } catch (Exception e) {
            log.info("[**======> {} **]", e.getMessage() + " >> " + e.getStackTrace()[0] + " >> " + e.getCause());
        }
        return "";
    }

    /**
     * yaml 2 json
     *
     * @param yamlStr yamlStr
     * @return
     */
    public static String yaml2JsonJack(String yamlStr) {
        try {
            ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
            Object obj = mapper.readValue(yamlStr, Object.class);
            ObjectMapper objectMapper = new ObjectMapper();
            return objectMapper.writeValueAsString(obj);
        } catch (Exception e) {
            log.info("[**======> {} **]", e.getMessage() + " >> " + e.getStackTrace()[0] + " >> " + e.getCause());
        }
        return "";
    }


    /**
     * ================================com.esotericsoftware.yamlbeans=========================================
     */


    /**
     * 将 Java 对象写到 yaml 文件
     * 注意, 此处转的yaml带有类型标注, 看起来不直观, 没有展开子类型
     *
     * @param object   对象
     * @param yamlPath 文件路径
     */
    public static void toYamlEso(Object object, String yamlPath) {
        try {
            YamlWriter writer = new YamlWriter(new FileWriter(yamlPath));
            writer.write(object);
            writer.close();
        } catch (Exception e) {
            log.info("[**======> {} **]", e.getMessage() + " >> " + e.getStackTrace()[0] + " >> " + e.getCause());
        }
    }


    /**
     * 从 yaml 文件读取转到 Java 对象
     *
     * @param yamlPath 文件路径
     * @param clazz    目标类.class
     * @param <T>      目标类
     * @return 目标类对象
     */
    public static <T> T toObjectEso(String yamlPath, Class<T> clazz) {
        try {
            YamlReader reader = new YamlReader(new FileReader(yamlPath));
            try {
                return reader.read(clazz);
            } catch (YamlException e) {
                log.info("[**======> {} **]", e.getMessage() + " >> " + e.getStackTrace()[0] + " >> " + e.getCause());
            }
        } catch (Exception e) {
            log.info("[**======> {} **]", e.getMessage() + " >> " + e.getStackTrace()[0] + " >> " + e.getCause());
        }
        return null;
    }


    /**
     * =================================snakeYaml==========================================
     */

    /**
     * Java 对象转 yaml 字符串
     *
     * @param object 对象
     * @return 字符串
     */
    public static String toYamlSnake(Object object) {
        Yaml yaml = new Yaml();
        StringWriter sw = new StringWriter();
        yaml.dump(object, sw);
        return sw.toString();
    }

    /**
     * yamlString 2 obj
     *
     * @param yamlStr yaml 字符串  无法根据Json注解获取不匹配字段的值
     * @param clazz   目标类.class
     * @param <T>     目标类
     * @return 目标类对象
     */
    @Deprecated
    public static <T> T toObjectSnake(String yamlStr, Class<T> clazz) {
        Yaml yaml = new Yaml();
        return yaml.loadAs(yamlStr, clazz);
    }

    /**
     * yamlPathFile 2 obj
     *
     * @param path   yamlPath  yamlString
     * @param tClass 目标类型对象
     * @param <T>    泛型
     * @return
     */
    public static <T> T pathToObjectSnake(String path, Class<T> tClass) {
        if (AssertNP.legalParams(path)) {
            Yaml yaml = new Yaml();
            try {
                return yaml.loadAs(new FileReader(path), tClass);
            } catch (Exception e) {
                log.info("[**======> {} **]", e.getMessage() + " >> " + e.getStackTrace()[0] + " >> " + e.getCause());
            }
        }
        return null;
    }


    /**
     * ==============================================================================
     */


    /**
     * yamlFile 2 yamlString or adjustYamlString
     * 注意传输yaml文件或字符串, 其他格式解析不了
     *
     * @param multipartFile multipartFile  yamlFile
     * @param context       yamlString
     * @return
     */
    public static String yamlFileOrYamlStr2String(MultipartFile multipartFile, String context) {
        String yamlContext = "";
        File file = null;
        try {
            file = parseToFile(multipartFile, context);
            Yaml yaml = new Yaml();
            if (AssertNP.legalParams(multipartFile, file)) {
                Map<Object, Object> load = yaml.load(new FileInputStream(file));
                yamlContext = yaml.dump(load);
            } else if (AssertNP.legalParams(context, file)) {
                return readFileToString(file);
            }
        } catch (Exception e) {
            //yamlContext = IOUtils.toString(new FileInputStream(file), "UTF-8");
            log.info("[**======> {} **]", e.getMessage() + " >> " + e.getStackTrace()[0] + " >> " + e.getCause());
        }
        return yamlContext;
    }


    /**
     * MultipartFile 2 File
     *
     * @param multipartFile multipartFile
     * @return
     */
    public static File getFileFromMultiPartFile(MultipartFile multipartFile) {
        File file = parseToFile(multipartFile, "");
        return file;
    }


    /**
     * String 2 File
     *
     * @param content
     * @return
     */
    public static File getFileFromStringContent(String content) {
        return parseToFile(null, content);
    }


    /**
     * StandardMultipartHttpServletRequest
     * multipartFile 转 File
     * string 转 File
     *
     * @param multipartFile multipartFile
     * @param context context
     * @return
     * @throws IOException
     */
    private static File parseToFile(MultipartFile multipartFile, String context) {
        //
        try {
            if (multipartFile != null) {
                Path temporary = Files.createTempFile("temporary", ".yaml");
                //StandardMultipartHttpServletRequest$StandardMultipartFile
                multipartFile.transferTo(temporary.toFile());
                return temporary.toFile();
            } else {
                log.info("\n" + context);
                File temporary = File.createTempFile("temporary", ".yaml");
                FileUtils.writeStringToFile(temporary, context);
                temporary.deleteOnExit();
                return temporary;
            }
        } catch (Exception e) {
            log.info("[**======> {} **]", e.getMessage() + " >>" + e.getStackTrace()[0] + " >>" + e.getCause());
        }
        return null;
    }


    /**
     * file 2 String
     *
     * @param file
     * @return
     */
    public static String readFileToString(File file) {
        String keyWords = "";
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(file));
            StringBuilder buffer = new StringBuilder();
            String keyStr = null;
            while ((keyStr = reader.readLine()) != null) {
                buffer.append(keyStr + "\n");
            }
            //去除字符串中的空格
            //String keyWords = buffer.toString().replaceAll("\\s*", "");
            keyWords = adjustStr(buffer.toString());
        } catch (Exception e) {
            log.info("[**======> {} **]", e.getMessage() + " >> " + e.getStackTrace()[0] + " >> " + e.getCause());
        } finally {
            ResourcesCloseUtils.close(reader);
        }
        return keyWords;
    }


    /**
     * 修剪yaml字符串
     *
     * @param src
     * @return
     */
    public static String adjustStr(String src) {
        return src.replaceAll("\\\\\\\\\n", "\n")
                .replaceAll("\\\\\\\\n", "\n")
                .replaceAll("\\\\\\\n", "\n")
                .replaceAll("\\\\\\n", "\n")
                .replaceAll("\\\\\n", "\n")
                .replaceAll("\\\\n", "\n")
                .replaceAll("\\\n", "\n")
                .replaceAll("\\n", "\n")
                .replaceAll("\n\n", "\n")
                .replaceAll("\n\n\n", "\n")
                .replaceAll("\n\n\n\n", "\n")
                .replaceAll("\n\n\n\n\n", "\n")
                .replaceAll("\n\n\n\n\n\n", "\n")
                .replaceAll("\n\n\n\n\n\n\n", "\n")
                .replaceAll("\n\n\n\n\n\n\n\n", "\n")
                ;
    }


    /**
     * @param context
     * @param path
     * @return
     */
    public static boolean writerStringToLocalFile(String context, String path) {
        BufferedOutputStream bos = null;
        boolean flag = true;
        try {
            bos = new BufferedOutputStream(new FileOutputStream(path));
            bos.write(context.getBytes());
        } catch (Exception e) {
            flag = false;
            log.info("[**======> {} **]", e.getMessage() + " >> " + e.getStackTrace()[0] + " >> " + e.getCause());
        } finally {
            ResourcesCloseUtils.close(bos);
        }
        return flag;
    }


    /**
     *
     * @return
     */
    public static String userDirCurrentPath() {
        //当前目录
        String currentPath = System.getProperty("user.dir");
        log.info("\n" + currentPath);
        return currentPath;
    }


    /**
     *
     * @return
     */
    public static String canonicalCurrentPath() {
        File directory = new File("");//设定为当前文件夹
        String canonicalPath = null;
        try {
            canonicalPath = directory.getCanonicalPath();
        } catch (Exception e) {
            log.info("[**======> {} **]", e.getMessage() + " >> " + e.getStackTrace()[0] + " >> " + e.getCause());
        }
        log.info("\n" + canonicalPath);
        return canonicalPath;
    }


    /**
     *
     * @return
     */
    public static String absoluteCurrentPath() {
        File directory = new File("");//设定为当前文件夹
        String absolutePath = directory.getAbsolutePath();
        log.info("\n" + absolutePath);
        return absolutePath;
    }


    /**
     *
     * @return
     */
    public static String osNameByManage() {
        return ManagementFactory.getOperatingSystemMXBean().getName();
    }


    /**
     *
     * @return
     */
    public static String osNameByProperties() {
        Properties properties=System.getProperties();
        return properties.getProperty("os.name");
    }

}

